home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / DVIM72-M / DVIM72.C < prev    next >
C/C++ Source or Header  |  1990-05-18  |  28KB  |  973 lines

  1. /* -*-C-*- dvim72.c */
  2. /*-->dvim72*/
  3. /**********************************************************************/
  4. /******************************* dvim72 *******************************/
  5. /**********************************************************************/
  6.  
  7. #include "dvihead.h"
  8.  
  9. #include "gendefs.h"
  10.  
  11. #include "m72.h"
  12.  
  13. #include "bitmap.h"
  14.  
  15. #if OS_THINKC
  16. #include "mac-specific.h"
  17. #include "PrintMgr.h"
  18. #endif
  19.  
  20. /* #include "main.h" */
  21. /**********************************************************************/
  22. /****************************** main.h *******************************/
  23. /**********************************************************************/
  24.  
  25. /**********************************************************************/
  26. /***********************  External Definitions  ***********************/
  27. /**********************************************************************/
  28.  
  29. #if    KCC_20
  30. #include <file.h>
  31. #endif /* KCC_20 */
  32.  
  33. #if    PCC_20                /* this stuff MUST be first */
  34.  
  35. #undef tops20                /* to keep definitions alive */
  36. #include <ioctl.h>            /* PCC-20 does not have this in */
  37.                     /* the others */
  38. #include <file.h>            /* need for f20open flags and */
  39.                     /* JSYS stuff */
  40. #define tops20  1            /* define for tops-20 */
  41. #endif /* PCC_20 */
  42.  
  43. #include "commands.h"
  44. #include <ctype.h>
  45. #include <math.h>
  46.  
  47. #if    OS_UNIX
  48. #if    BSD42
  49.  
  50. #include <sys/ioctl.h>            /* need for DVISPOOL in dviterm.h */
  51.  
  52. #ifndef _NFILE
  53. /* VAX VMS, NMTCC, PCC-20, and HPUX have _NFILE in stdio.h.  V7 called
  54. it NFILE, and Posix calls it OPEN_MAX.  KCC-20 calls it SYS_OPEN.  VAX
  55. 4.3BSD and Gould UTX/32 don't define _NFILE in stdio.h; they use
  56. NOFILE from sys/param.h.  Sigh.... */
  57. #include <sys/param.h>
  58. #ifdef NOFILE
  59. #define _NFILE NOFILE            /* need for gblvars.h */
  60. #else
  61. #define _NFILE MAXOPEN            /* use our font limit value */
  62. #endif
  63. #endif
  64.  
  65. #endif /* BSD42 */
  66. #endif /* OS_UNIX */
  67.  
  68. #include "gblprocs.h"
  69.  
  70. #include "gblvars.h"
  71.  
  72. #if    OS_ATARI
  73. long _stksize = 20000L; /* make the stack a bit larger than 2KB */
  74.                         /* number must be even                  */
  75. #endif /* OS_ATARI */
  76.  
  77.  
  78. /**********************************************************************/
  79. /*******************************  main  *******************************/
  80. /**********************************************************************/
  81. #if !OS_THINKC
  82. int
  83. main(
  84. #if OS_THINKC
  85. #else
  86. int argc, char *argv[]
  87. #endif
  88. )
  89. {
  90.     register int k;        /* loop index */
  91.     register int file_args;    /* count of file arguments */
  92.  
  93. #if OS_THINKC
  94.     int argc;
  95.     char *argv[MAX_ARGS];
  96.  
  97.     get_args( &argc, argv );
  98.     if (argc < 2) /* no DVI file specified */
  99.         exit(0);
  100.     printf("THINK C DVIM72-Mac version 0.1b starting.\n");
  101.     printf("Printing <%s>.\n", argv[1]);
  102. #endif
  103.  
  104.     (void)strcpy(g_progname, argv[0]); /* save program name */
  105.  
  106.     (void)initglob();        /* do this before argc check! */
  107.  
  108. #if    OS_UNIX | OS_THINKC
  109.     /* On Unix, we allow filtering of stdin to stdout */
  110.     /* In THINK C, we put up a standard file dialog to get the .dvi file */
  111. #else /* NOT OS_UNIX */
  112.     if (argc < 2)
  113.     {
  114.     (void)usage(stderr);
  115.     (void)EXIT(1);
  116.     }
  117. #endif /* OS_UNIX */
  118.  
  119.     for (k = 1; k < argc; ++k)
  120.     {
  121.     if (*argv[k] == '-')    /* -switch */
  122.         (void)option(argv[k]);
  123.     }
  124.  
  125.     if (!quiet)
  126.     {
  127.     (void)fprintf(stderr,"[TeX82 DVI Translator Version %s]",VERSION_NO);
  128.     NEWLINE(stderr);
  129.     (void)fprintf(stderr,"[%s]",DEVICE_ID);
  130.     NEWLINE(stderr);
  131.     }
  132.  
  133.     if (npage == 0)        /* no page ranges given, make a large one */
  134.     {
  135.         page_begin[0] = 1;
  136.         page_end[0] = 32767;    /* arbitrary large integer */
  137.         page_step[0] = 1;
  138.         npage = 1;
  139.     }
  140.     else /* need font defs from postamble if only some pages to be output */
  141.         preload = TRUE;
  142.  
  143.     file_args = 0;
  144.     for (k = 1; k < argc; ++k)
  145.     {
  146.         if (*argv[k] != '-')     /* must be file argument */
  147.         {
  148.               file_args++;
  149.             (void)dvifile(argc,argv,argv[k]);
  150.         }
  151.     }
  152.  
  153. #if    OS_UNIX
  154.     if (file_args == 0)        /* use stdin/stdout instead */
  155.         (void)dvifile(argc,argv,"");
  156. #endif
  157.  
  158.     (void)alldone();        /* this will never return */
  159.     return (0);            /* never executed; avoid compiler warnings */
  160. }
  161. #endif /* !OS_THINKC */
  162. /**********************************************************************/
  163. /**********************************************************************/
  164. /**********************************************************************/
  165.  
  166.  
  167. /* #include "abortrun.h" */
  168. /* #include "actfact.h" */
  169. /* #include "alldone.h" */
  170. /* #include "chargf.h" */
  171. /* #include "charpk.h" */
  172. /* #include "charpxl.h" */
  173. /* #include "clrbmap.h" */
  174.  
  175. /* #include "clrrow.h" */
  176. /* #include "dbgopen.h" */
  177.  
  178. /*-->devinit*/
  179. /**********************************************************************/
  180. /****************************** devinit *******************************/
  181. /**********************************************************************/
  182. #if OS_THINKC
  183. #else /* not OS_THINKC */
  184. void
  185. devinit(argc,argv)        /* initialize device */
  186. int argc;
  187. char *argv[];
  188. {
  189.     (void)getbmap();
  190.     if (runlengthcode && !quiet)
  191.     {
  192.     (void)fprintf(stderr,"[Run-length encoding of output file]");
  193.     NEWLINE(stderr);
  194.     }
  195. }
  196. #endif  /* OS_THINKC */
  197.  
  198. /*-->devterm*/
  199. /**********************************************************************/
  200. /****************************** devterm *******************************/
  201. /**********************************************************************/
  202.  
  203. void
  204. devterm()            /* terminate device */
  205. {
  206. #if OS_THINKC
  207.     Close_printer();
  208. #endif
  209. }
  210.  
  211. /* #include "dispchar.h" */
  212. /* #include "dvifile.h" */
  213.  
  214. /* #include "dviinit.c" */
  215. /* #include "dviterm.h" */
  216. /* #include "f20open.h" */
  217. /* #include "fatal.h" */
  218. /* #include "fillrect.h" */
  219. /* #include "findpost.h" */
  220. /* #include "fixpos.h" */
  221. /* #include "fontfile.h" */
  222. /* #include "fontsub.h" */
  223. /* #include "getbmap.h" */
  224. /* #include "getbytes.h" */
  225. /* #include "getfntdf.h" */
  226. /* #include "getpgtab.h" */
  227. /* #include "inch.h" */
  228. /* #include "initglob.h" */
  229. /* #include "loadchar.h" */
  230.  
  231. /*-->makechar*/
  232. /**********************************************************************/
  233. /****************************** makechar ******************************/
  234. /**********************************************************************/
  235.  
  236. char
  237. makechar(p,mask)
  238. register UNSIGN32* p[];
  239. register UNSIGN32 mask;
  240. {
  241.     register char c;
  242.  
  243. #if    SEGMEM
  244. #define Q(n) p[n]            /* use precomputed pointers */
  245. #else /* NOT SEGMEM */
  246. #define Q(n) (p[0] - (n)*XBIT)        /* compute pointers on the fly */
  247. #endif /* SEGMEM */
  248.  
  249.     c = '\000';
  250.  
  251. #if    HIRES
  252.     if (*Q(0) & mask)
  253.     c |= '\001';
  254.     if (*Q(2) & mask)
  255.     c |= '\002';
  256.     if (*Q(4) & mask)
  257.     c |= '\004';
  258.     if (*Q(6) & mask)
  259.     c |= '\010';
  260.     if (*Q(8) & mask)
  261.     c |= '\020';
  262.     if (*Q(10) & mask)
  263.     c |= '\040';
  264.     if (*Q(12) & mask)
  265.     c |= '\100';
  266.     if (*Q(14) & mask)
  267.     c |= '\200';
  268. #else
  269.     if (*Q(0) & mask)
  270.     c |= '\001';
  271.     if (*Q(1) & mask)
  272.     c |= '\002';
  273.     if (*Q(2) & mask)
  274.     c |= '\004';
  275.     if (*Q(3) & mask)
  276.     c |= '\010';
  277.     if (*Q(4) & mask)
  278.     c |= '\020';
  279.     if (*Q(5) & mask)
  280.     c |= '\040';
  281.     if (*Q(6) & mask)
  282.     c |= '\100';
  283.     if (*Q(7) & mask)
  284.     c |= '\200';
  285. #endif
  286.  
  287.     return(c);
  288. }
  289.  
  290. /* #include "movedown.h" */
  291. /* #include "moveover.h" */
  292. /* #include "moveto.h" */
  293. /* #include "nosignex.h" */
  294. /* #include "openfont.h" */
  295. /**********************************************************************/
  296. /****************************** openfont ******************************/
  297. /**********************************************************************/
  298.  
  299. void
  300. openfont(fontname)
  301. char *fontname;
  302.  
  303. /***********************************************************************
  304.     The original version of this DVI driver reopened the font file  each
  305.     time the font changed, resulting in an enormous number of relatively
  306.     expensive file  openings.    This version  keeps  a cache  of  up  to
  307.     MAXOPEN open files,  so that when  a font change  is made, the  file
  308.     pointer, fontfp, can  usually be  updated from the  cache.  When the
  309.     file is not found in  the cache, it must  be opened.  In this  case,
  310.     the next empty slot  in the cache  is assigned, or  if the cache  is
  311.     full, the least used font file is closed and its slot reassigned for
  312.     the new file.  Identification of the least used file is based on the
  313.     counts of the number  of times each file  has been "opened" by  this
  314.     routine.  On return, the file pointer is always repositioned to  the
  315.     beginning of the file.
  316.  
  317.     If the first open attempt  fails, an attempt will  be made to use  a
  318.     substitute font, then neighboring magnifications (with the same font
  319.     name), or substitutes for them.
  320. ***********************************************************************/
  321.  
  322. {
  323.     register INT16 i,j,k;    /* loop indices */
  324.     INT16 current;
  325.     INT16 least_used;
  326.     INT16 maxopen = MAXOPEN;
  327.    float resfact = RESOLUTION / 200.0;
  328.  
  329. #if    OS_VAXVMS
  330.     long *jpi;
  331. #endif
  332.  
  333.     struct font_entry *tfontptr;
  334.     char subfont[MAXFNAME];
  335.     int submag;
  336.     char* filelist[MAXFORMATS];    /* pointers to templist[][] */
  337.     char templist[MAXFORMATS][MAXFNAME];
  338.  
  339. #if    VIRTUAL_FONTS
  340.     struct stat statbuf;        /* so fstat() can get file size */
  341.     char *p;
  342. #endif
  343.  
  344.     if ((pfontptr != (struct font_entry *)NULL) && (pfontptr == fontptr))
  345.     return;            /* we need not have been called */
  346.  
  347.     for (j = 0; j < MAXFORMATS; ++j)    /* initialize fontlist pointers */
  348.     filelist[j] = &templist[j][0];
  349.  
  350. #if    IBM_PC_MICROSOFT
  351.     /* This code required rewriting to get around a fatal compiler
  352.     assertion error occasioned by the code in the #else part */
  353.     for (current = 1; current <= nopen; ++current)
  354.     {
  355.         FILE* pfp;
  356.  
  357.     pfp = font_files[current].font_id;
  358.     if (pfp == fontptr->font_file_id)
  359.         break;
  360.     }
  361. #else
  362.     for (current = 1;
  363.         (current <= nopen) &&
  364.         (font_files[current].font_id != fontptr->font_file_id);
  365.         ++current)
  366.     ;            /* try to find file in open list */
  367. #endif
  368.  
  369.     if (current <= nopen)    /* file already open, lookup its id */
  370.         fontfp = font_files[current].font_id;
  371.     else
  372.     {
  373.     /***************************************************************
  374.     The file was  not in list  of open  files.  If the  list is  not
  375.     full, add it to  the list; otherwise  close the least-used  file
  376.     and remove it from the font_entry containing it.  Finally,  open
  377.     the file, or its closest  neighbor in the magnification  family.
  378.     A warning is issued  if no file can  be opened.  The caller  can
  379.     then proceed with zero font metrics if desired.
  380.     ***************************************************************/
  381.  
  382. #if    OS_VAXVMS
  383.         /***************************************************************
  384.     VAX VMS has many user quotas, one of which is the maximum number
  385.     of files  that can be open, which  need have no relation  to the
  386.     number  that C  permits.  If  we do  not determine the  limit at
  387.     run-time, the drivers may attempt to open too many files, and in
  388.     such a case, will fail.   There  are two relevant  quotas, FILLM
  389.     (open file limit), and  FILCNT (remaining open file quota).   We
  390.     use the latter,  and leave  one available file  for a   possible
  391.     error log.
  392.     ***************************************************************/
  393.  
  394.     jpi = (long*)getjpi(JPI$_FILCNT);
  395.     if (jpi == (long*)NULL)
  396.         maxopen = MAXOPEN;        /* should never happen */
  397.     else
  398.         maxopen = nopen - 1 + *jpi;
  399.     maxopen = MIN(maxopen,MAXOPEN);    /* we have arrays of size MAXFONT */
  400.                     /* so do not exceed that limit */
  401. #endif /* OS_VAXVMS */
  402.  
  403.     if (nopen < maxopen)    /* just add it to list */
  404.         current = ++nopen;
  405.     else            /* list full -- find least used file, */
  406.     {            /* close it, and reuse slot for new file */
  407.         least_used = 1;
  408.         for (i = 2; i <= maxopen; ++i)
  409.             if (font_files[least_used].use_count >
  410.                     font_files[i].use_count)
  411.                 least_used = i;
  412.  
  413.         fontfp = font_files[least_used].font_id;
  414.         tfontptr = hfontptr;
  415.         while (tfontptr != (struct font_entry*)NULL)
  416.         {            /* remove file pointer from its font_entry */
  417.             if (tfontptr->font_file_id == fontfp)
  418.             {
  419.                 tfontptr->font_file_id = (FILE*)NULL;
  420.                 break;
  421.             }
  422.             tfontptr = tfontptr->next;
  423.         }
  424.  
  425. #if    VIRTUAL_FONTS
  426.         if (virt_font && (fontfp != (FILE*)NULL))
  427.             (void)virtfree(fontfp);
  428. #endif
  429.  
  430.         (void)fclose(fontfp);
  431.         fontfp = (FILE*)NULL;
  432.         current = least_used;
  433.     }
  434.     (void)actfact_res(fontptr->font_mag);    /* Get global mag_index */
  435.  
  436.     fontfp = (FILE*)NULL;
  437.  
  438.     /***************************************************************
  439.     Try the requested font, then any substitute font, then for  each
  440.     neighboring magnification  from  nearest to  furthest,  try  the
  441.     requested font, and then any substitute font.
  442.     ***************************************************************/
  443.  
  444.     for (k = 0; (fontfp == (FILE*)NULL) && (k < MAGTABSIZE); ++k)
  445.     {                /* loop over mag family */
  446.         for (i = -k; (fontfp == (FILE*)NULL) && (i <= k); i += MAX(1,k+k))
  447.         {                /* try smaller, then larger */
  448.             if (IN(0,mag_index+i,MAGTABSIZE-1))
  449.             {
  450.                 (void)fontfile(filelist, ((fontptr->a==0)?fontpath:""),
  451.                 fontname, (int)MAGSIZE(mag_table[mag_index+i]*resfact));
  452.                 for (j = 0; (j < MAXFORMATS) && *filelist[j]; ++j)
  453.                 {
  454.                     fontfp = FOPEN(filelist[j],RB_OPEN);
  455.                     DEBUG_OPEN(fontfp,filelist[j],RB_OPEN);
  456.                     if (fontfp != (FILE *)NULL)
  457.                     {
  458.                         strcpy(fontptr->name,filelist[j]);
  459.                         break;
  460.                     }
  461.                 }
  462.                 if ((k > 0) && (fontfp != (FILE*)NULL))
  463.                 {
  464.                 (void)sprintf(message,
  465.                     "Font file [%s [mag %d]] could not be opened.\n"
  466.                     "---using nearest neighbor [%s [mag %d]] instead.",
  467.                     fontname,(int)MAGSIZE(mag_table[mag_index]*resfact),
  468.                     fontptr->name,
  469.                     (int)MAGSIZE(mag_table[mag_index+i]*resfact));
  470.                 (void)warning(message);
  471.                 }
  472.     
  473.                 if ((fontfp == (FILE*)NULL) && fontsub(subfont,&submag,
  474.                 fontname,(int)MAGSIZE(mag_table[mag_index+i]*resfact)))
  475.                 {
  476.                     (void)fontfile(filelist,((fontptr->a==0)?fontpath:""),
  477.                         subfont,(submag ? submag :
  478.                         (int)MAGSIZE(mag_table[mag_index+i]*resfact)));
  479.                     for (j = 0; (j < MAXFORMATS) && *filelist[j]; ++j)
  480.                     {
  481.                         fontfp = FOPEN(filelist[j],RB_OPEN);
  482.                         DEBUG_OPEN(fontfp,filelist[j],RB_OPEN);
  483.                         if (fontfp != (FILE *)NULL)
  484.                         {
  485.                             strcpy(fontptr->name,filelist[j]);
  486.                             break;
  487.                         }
  488.                     }
  489.         
  490.                     if (fontfp != (FILE*)NULL)
  491.                     {
  492.                         (void)sprintf(message,
  493.                         "Substituting font file [%s [mag %d]] "
  494.                         "by [%s [mag %d]]",
  495.                         fontname, submag,
  496.                         /* (int)MAGSIZE(mag_table[mag_index]*resfact), */
  497.                         fontptr->name,
  498.                         (int)MAGSIZE(mag_table[mag_index+i]*resfact));
  499.                         (void)warning(message);
  500.                     }
  501.                 }
  502.             }
  503.         } /* end for (i) -- loop over smaller and larger neighbors  */
  504.     } /* end for (k) -- loop over mag family */
  505.  
  506.     if (fontfp == (FILE*)NULL)
  507.     {
  508.         --nopen;            /* don't count this failed open */
  509.         (void)sprintf(message,"Font file [%s [mag %d]] could not be \
  510. opened; %d font files are open\n\
  511. Proceeding with zero size characters for this font",
  512.         fontname,(int)MAGSIZE(mag_table[mag_index]*resfact),nopen);
  513.         (void)warning(message);
  514.     }
  515.  
  516.     font_files[current].font_id = fontfp;
  517.     font_files[current].use_count = 0;
  518.  
  519. #if    VIRTUAL_FONTS
  520.     /*
  521.     ****************************************************************
  522.     This code  is implementation-dependent.   On many  C  compilers,
  523.     FILE points to a struct of the form
  524.  
  525.     struct    _iobuf {
  526.         char    *_ptr;    // pointer to next available char
  527.         int    _cnt;    // number of chars left in buffer
  528.         char    *_base;    // pointer to start of buffer
  529.         int    _flag;    // assorted flags
  530.         int    _file;    // file number handle
  531.         }
  532.  
  533.     To implement virtual fonts,  we save the  pointers in a  private
  534.     global array, get the file size from fstat(), malloc() a  buffer
  535.     for it, read the entire file in, and replace the pointers in the
  536.     FILE variable with ones  for  the  new buffer.  Just before  the
  537.     file is  closed, the space is  freed  and the   old pointers are
  538.     restored.   Although many C implementations use  malloc() to get
  539.     the buffer  space  in the  first place, which  would  make  this
  540.     saving unnecessary, not all do; see  the implementation given in
  541.     Kernighan and Ritchie "The C Programming Language", p. 168.
  542.  
  543.     In  implementing   this   code   on   any   new   machine,   the
  544.     implementations of fread(), read(), fseek(), and rewind() should
  545.     be checked to  choose the  most efficient one  (e.g. one  system
  546.     call for entire file  read, and no  double buffering), and  make
  547.     sure that  fseek() and  rewind()  do not  unnecessarily  discard
  548.     input buffer  contents.  fseek()  and  rewind() are  defined  in
  549.     terms of macros FSEEK() and REWIND() in machdefs.h to facilitate
  550.     replacement.
  551.     ****************************************************************
  552.     */
  553.     if (virt_font)
  554.     {
  555.         virt_save[fileno(fontfp)].base = (char *)NULL;
  556.         (void)fstat(fileno(fontfp),&statbuf);    /* get file size */
  557.         p = (char *)MALLOC((int)statbuf.st_size);    /* get file buffer */
  558.         if (p != (char *)NULL)
  559.         {
  560.         if (READ(fileno(fontfp),p,(int)statbuf.st_size)
  561.              == (int)statbuf.st_size)
  562.         {            /* read successful */
  563.             virt_save[fileno(fontfp)].ptr = FILE_PTR(fontfp);
  564.             virt_save[fileno(fontfp)].cnt = FILE_CNT(fontfp);
  565.             virt_save[fileno(fontfp)].base = FILE_BASE(fontfp);
  566.             FILE_PTR(fontfp) = p;
  567.             FILE_BASE(fontfp) = p;
  568.             FILE_CNT(fontfp) = (int)statbuf.st_size;
  569.         }
  570.         else            /* failure */
  571.         {
  572.             (void)REWIND(fontfp);
  573.             (void)free(p);    /* free dynamic buffer */
  574.         }
  575.         }
  576.         if (DBGOPT(DBG_FONT_CACHE))
  577.         {
  578.             (void)fprintf(stderr,"\nopenfont(): Font file %d [%s] ",
  579.             (int)fileno(fontfp),fontptr->name);
  580.             if (p == (char *)NULL)
  581.             (void)fprintf(stderr,
  582.             "cannot callocate buffer for entire file\n");
  583.         else
  584.             (void)fprintf(stderr,
  585.             "buffer length 0x%x\told buffer at 0x%lx\t\
  586. new buffer at 0x%lx\n",
  587.             (int)statbuf.st_size,
  588.             (long)virt_save[fileno(fontfp)].base,
  589.             (long)FILE_BASE(fontfp));
  590.         }
  591.     }
  592. #endif
  593.  
  594.     } /* end if (file is in open list) */
  595.  
  596.     pfontptr = fontptr;            /* make previous = current font */
  597.     fontptr->font_file_id = fontfp;    /* set file identifier */
  598.     font_files[current].use_count++;    /* update reference count */
  599. }
  600.  
  601. #if    VIRTUAL_FONTS
  602. void
  603. virtfree(fp)                /* free buffer space before close */
  604. FILE *fp;
  605. {
  606.     if (virt_font && (fp != (FILE*)NULL) &&
  607.     (virt_save[fileno(fp)].base != (char *)NULL))
  608.     {
  609.     (void)fflush(fp);
  610.     (void)free(FILE_BASE(fp));
  611.     FILE_PTR(fp) = virt_save[fileno(fp)].ptr;
  612.     FILE_CNT(fp) = virt_save[fileno(fp)].cnt;
  613.     FILE_BASE(fp) = virt_save[fileno(fp)].base;
  614.     virt_save[fileno(fp)].base = (char *)NULL;
  615.     }
  616. }
  617. #endif
  618.  
  619. /* #include "option.h" */
  620.  
  621. #if !OS_THINKC /* this routine is not needed in dvim72-Mac */
  622. /*-->outline*/
  623. /**********************************************************************/
  624. /****************************** outline *******************************/
  625. /**********************************************************************/
  626. /* The name outline conflicts with a QuickDraw constant. */
  627. #if OS_THINKC
  628. #define outline rloutl
  629. #endif
  630.  
  631. void
  632. outline(pline)
  633. char *pline;
  634.  
  635. {
  636.     register INT16 left;
  637.     register char *a,*b,*c;
  638.     INT16 len;
  639.  
  640.     for ((left = XSIZE, c = pline + XSIZE - 1);
  641.     (*c == '\000') && (left > 1);
  642.     (--left,--c))            /* trim white space but leave */
  643.     ;                /* at least 1 character in line */
  644.  
  645.     /*******************************************************************
  646.     We search for runs as follows.  "b" marks the beginning of unwritten
  647.     data, and "a" anchors the beginning of a run which continues to just
  648.     before "c".   The  run length  is  "c"-"a".  Since  the  run  length
  649.     encoding carries a penalty of additional output equal to the  length
  650.     of the  run  length  prefix  (<ESC>Vnnnn), short  runs  are  not  so
  651.     encoded.
  652.  
  653.     If a long  enough run  is found,  then the  string "b"  .. "a"-1  is
  654.     output since its length is now  known, followed by the run  encoding
  655.     for the character at "a".  Then "a" and "b" are advanced to "c", and
  656.     the scan continues.
  657.  
  658.     If the  run  beginning at  "a"  is too  short,  then "a"  is  simply
  659.     advanced.
  660.  
  661.     Since the  character strings  take on  all values  on 0  .. 255,  we
  662.     cannot store a termination marker, but must instead keep a  counter,
  663.     "left", which is  decremented to  0 when the  end of  the string  is
  664.     reached.
  665.  
  666.     ?????????????xxxxxxxxxxxxxxxx????????????????????
  667.     ^            ^               ^
  668.     |            |               |
  669.     b            a               c
  670.  
  671.                  <-----run------>
  672.     *******************************************************************/
  673.  
  674.     if (runlengthcode && (left > 7))
  675.     {
  676.     for (a = b = pline; (left > 0); --left)
  677.     {
  678.         for (c = a; (*a == *++c) && left; --left)
  679.         ;                /* advance over run */
  680.         len = (INT16)(c-a);            /* "c" points past run */
  681.         if (len > 7)            /* output long run */
  682.         {
  683.             if (a > b)            /* output previous string */
  684.         {
  685.             if ((int)(a-b) & 07)
  686.                 OUTF("\033G%04d",(int)(a - b));
  687.             else
  688.                 OUTF("\033g%03d",((int)(a - b)) >> 3);
  689.             for ( ; b < a; b++)
  690.                 OUTC(*b);
  691.         }
  692.         OUTF2("\033V%04d%c",len,*a);
  693.         a = b = c;
  694.         }
  695.         else                /* ignore short run */
  696.         {
  697.         ++a;
  698.         left += len - 1;
  699.         }
  700.     }
  701.     if (a > b)        /* output remaining string */
  702.     {
  703.         if ((int)(a-b) & 07)
  704.             OUTF("\033G%04d",(int)(a - b));
  705.         else
  706.             OUTF("\033g%03d",((int)(a - b)) >> 3);
  707.         for ( ; b < a; b++)
  708.         OUTC(*b);
  709.     }
  710.     }
  711.     else                /* no runlength coding */
  712.     {
  713.         if (left & 07)
  714.         OUTF("\033G%04d",left);
  715.     else
  716.         OUTF("\033g%03d",left >> 3);
  717.  
  718.     /* cannot use fprintf %s because 0 bytes terminate string */
  719.     for (c = pline; left; --left, c++)
  720.         OUTC(*c);
  721.     }
  722.     NEWLINE(plotfp);
  723. }
  724. #endif /* !OS_THINKC */
  725.  
  726. /* #include "outrow.h" */
  727.  
  728. /*-->prtbmap*/
  729. /**********************************************************************/
  730. /****************************** prtbmap *******************************/
  731. /**********************************************************************/
  732.  
  733. void
  734. prtbmap()
  735. {
  736. #if OS_THINKC
  737.     Print_page();
  738. }
  739. #else
  740.     register BYTE *c;            /* pointer into v8[][] */
  741.     UNSIGN32 *p;            /* pointer into bitmap[][] */
  742.  
  743. #if    SEGMEM
  744. #else
  745.     UNSIGN32 *ptmp;            /* pointer into bitmap[][] */
  746. #endif /* SEGMEM */
  747.  
  748.     register UNSIGN32 mask;        /* mask for single bit selection */
  749.     register INT16 k;
  750.     INT16 i,j,ybottom,ytop;
  751.  
  752. #if    HIRES
  753.     BYTE v8[2][XSIZE];            /* vertical 8-bit raster encodings */
  754.  
  755. #undef Q
  756. #if    SEGMEM
  757.     UNSIGN32* q[16];            /* pointers to 16 raster lines */
  758. #define Q(n) q[n]            /* use precomputed pointers */
  759. #else /* NOT SEGMEM */
  760. #define Q(n) (p - (n)*XBIT)        /* compute pointers on the fly */
  761. #endif /* SEGMEM */
  762.  
  763.     (void)clearerr(plotfp);
  764.  
  765.     ytop = YBIT-1;
  766.  
  767.     k = -1;        /* find bottom non-zero raster */
  768.     for (j = 0; (j < ytop) && (k < 0); ++j) /* loop over raster lines */
  769.     {
  770.  
  771. #if    IBM_PC_MICROSOFT
  772.     for (k = XBIT - 1; ((k >= 0) && (*BITMAP(j,k) == 0)); --k)
  773.         ;            /* trim white space */
  774.  
  775. #else
  776.     p = BITMAP(j,XBIT-1);
  777.     for (k = XBIT - 1; ((k >= 0) && (*p == 0)); --k)
  778.         --p;        /* trim white space */
  779. #endif /* IBM_PC_MICROSOFT */
  780.  
  781.     }
  782.     ybottom = (j/16)*16 + 15;
  783.  
  784.     OUTS("\033c");            /* reset printer */
  785.     (void)putc('\0', plotfp);
  786.     (void)putc('\0', plotfp);
  787.     (void)putc('\0', plotfp);
  788.     (void)putc('\0', plotfp);
  789.     (void)putc('\0', plotfp);
  790.  
  791.     for (j = ytop; (j >= ybottom) ; j -= 16)   /* loop over raster lines */
  792.                            /* in groups of 16 */
  793.     {
  794.  
  795. #if    SEGMEM
  796. #else
  797.     p = BITMAP(j,0);    /* the j-th raster line */
  798. #endif
  799.  
  800.     c = &v8[0][0];        /* vertical 8-bit encodings */
  801.     for (i = 0; i < XBIT; (++p,++i))    /* loop over raster words */
  802.     {
  803.         /* PCC-20 compiled (1 << (HOST_WORD_SIZE-1)) to 0, so do it the
  804.            hard way, arghh... */
  805.         mask = 1;
  806.         mask <<= (HOST_WORD_SIZE-1);    /* to select leftmost bit */
  807.  
  808. #if    SEGMEM
  809.         for (k = 0; k < 16; ++k)    /* compute pointers to 16 rasters */
  810.             q[k] = BITMAP(j-k,i);
  811. #endif /* SEGMEM */
  812.  
  813.         for (k = 0; k < HOST_WORD_SIZE; (++c,++k))/* loop over word bits */
  814.         {
  815.         /* examine bits in 16 adjacent rows and build two 8-bit */
  816.         /* character values, the first with rows n,n+2,...,n+14, */
  817.         /* the second with rows n+1,n+3,...,n+15.  The two */
  818.         /* characters are then printed with 1 dot vertical spacing */
  819.  
  820. #if    SEGMEM
  821.         *c = (BYTE)makechar(&q[0],mask);
  822.         *(c+XSIZE) = (BYTE)makechar(&q[1],mask);
  823. #else
  824.         *c = (BYTE)makechar(&p,mask);
  825.         ptmp = p - XBIT;
  826.         *(c+XSIZE) = (BYTE)makechar(&ptmp,mask);
  827. #endif /* SEGMEM */
  828.  
  829.         mask >>= 1;        /* move masking bit right 1 position */
  830.         }                /* end loop over k */
  831.     }                /* end loop over i */
  832.  
  833.     /* ESC p for 144 dots/inch horizontally */
  834.     /* ESC T01 for 1/144 inch spacing */
  835.     /* ESC g nnn for length/8 count */
  836.     OUTS("\033p\033T01");
  837.     (void)outline((char *)&v8[0][0]);
  838.  
  839.     /* ESC p for 144 dots/inch horizontally */
  840.     /* ESC T15 for 15/144 inch spacing */
  841.     /* ESC g nnn for length/8 count */
  842.     OUTS("\033p\033T15");
  843.     (void)outline((char *)&v8[1][0]);
  844.     }                    /* end loop over j */
  845.  
  846.     OUTC('\f');                /* eject page with FF */
  847.     OUTS("\033c");            /* reset printer */
  848.     (void)putc('\0', plotfp);
  849.     (void)putc('\0', plotfp);
  850.     (void)putc('\0', plotfp);
  851.     (void)putc('\0', plotfp);
  852.  
  853.     (void)fflush(plotfp);
  854.     if (DISKFULL(plotfp))
  855.     (void)fatal("prtbmap(): Output error -- disk storage probably full");
  856. }
  857. #else /* NOT HIRES */
  858.     BYTE v8[XSIZE+2];            /* vertical 8-bit raster encodings */
  859.  
  860. #undef Q
  861. #if    SEGMEM
  862.     UNSIGN32* q[8];            /* pointers to 8 raster lines */
  863. #define Q(n) q[n]            /* use precomputed pointers */
  864. #else /* NOT SEGMEM */
  865. #define Q(n) (p - (n)*XBIT)        /* compute pointers on the fly */
  866. #endif /* SEGMEM */
  867.  
  868.     ytop = YBIT-1;
  869.  
  870.     k = -1;        /* find bottom non-zero raster */
  871.     for (j = 0; (j < ytop) && (k < 0); ++j) /* loop over raster lines */
  872.     {
  873.  
  874. #if    IBM_PC_MICROSOFT
  875.     for (k = XBIT - 1; ((k >= 0) && (*BITMAP(j,k) == 0)); --k)
  876.         ;                /* trim white space */
  877. #else
  878.     p = BITMAP(j,XBIT-1);
  879.     for (k = XBIT - 1; ((k >= 0) && (*p == 0)); --k)
  880.         --p;            /* trim white space */
  881. #endif /* IBM_PC_MICROSOFT */
  882.  
  883.     }                    /* end loop over j */
  884.     ybottom = (j/8)*8 + 7;
  885.  
  886.     OUTS("\033c");            /* reset printer */
  887.     (void)putc('\0', plotfp);
  888.     (void)putc('\0', plotfp);
  889.     (void)putc('\0', plotfp);
  890.     (void)putc('\0', plotfp);
  891.  
  892.     for (j = ytop; (j >= ybottom) ; j -= 8)    /* loop over raster lines */
  893.                            /* in groups of 8 */
  894.     {
  895.  
  896. #if    SEGMEM
  897. #else
  898.     p = BITMAP(j,0);    /* the j-th raster line */
  899. #endif /* SEGMEM */
  900.  
  901.     c = &v8[0];        /* vertical 8-bit encodings */
  902.     for (i = 0; i < XBIT; (++p,++i))    /* loop over raster words */
  903.     {
  904.         /* PCC-20 compiled (1 << (HOST_WORD_SIZE-1)) to 0, so do it the
  905.            hard way, arghh... */
  906.         mask = 1;
  907.         mask <<= (HOST_WORD_SIZE-1);    /* to select leftmost bit */
  908.  
  909. #if    SEGMEM
  910.         for (k = 0; k < 8; ++k)    /* compute pointers to 8 rasters */
  911.             q[k] = BITMAP(j-k,i);
  912. #endif /* SEGMEM */
  913.  
  914.         for (k = 0; k < HOST_WORD_SIZE; (++c,++k))/* loop over word bits */
  915.         {
  916.         /* examine bits in 8 adjacent rows and build 8-bit */
  917.         /* character value */
  918.  
  919. #if    SEGMEM
  920.         *c = (BYTE)makechar(q,mask);
  921. #else
  922.         *c = (BYTE)makechar(&p,mask);
  923. #endif /* SEGMEM */
  924.  
  925.         mask >>= 1;        /* move masking bit right 1 position */
  926.         }                /* end loop over k */
  927.     }                /* end loop over i */
  928.     --c;                /* last character encoded */
  929.  
  930.     /* ESC n for 72 dots/inch horizontally */
  931.     /* ESC T16 for 16/144 inch spacing */
  932.     /* ESC G nnnn for length count */
  933.     OUTS("\033n\033T16");
  934.     (void)outline((char *)&v8[0]);
  935.     }                    /* end loop over j */
  936.     OUTC('\f');                /* eject page with FF */
  937.     OUTS("\033c");            /* reset printer */
  938.     (void)putc('\0', plotfp);
  939.     (void)putc('\0', plotfp);
  940.     (void)putc('\0', plotfp);
  941.     (void)putc('\0', plotfp);
  942.  
  943.     (void)fflush(plotfp);
  944.     if (DISKFULL(plotfp))
  945.     (void)fatal("prtbmap(): Output error -- disk storage probably full");
  946. }
  947. #endif /* HIRES */
  948. #endif /* OS_THINKC */
  949.  
  950. /* #include "prtpage.h" */
  951. /* #include "readfont.h" */
  952. /* #include "readgf.h" */
  953. /* #include "readpk.h" */
  954. /* #include "readpost.h" */
  955. /* #include "readpxl.h" */
  956. /* #include "reldfont.h" */
  957. /* #include "rulepxl.h" */
  958. /* #include "setchar.h" */
  959. /* #include "setfntnm.h" */
  960. /* #include "setrule.h" */
  961. /* #include "signex.h" */
  962. /* #include "skgfspec.h" */
  963. /* #include "skipfont.h" */
  964. /* #include "skpkspec.h" */
  965. /* #include "special.h" */
  966. /* #include "strchr.h" */
  967. /* #include "strcm2.h" */
  968. /* #include "strid2.h" */
  969. /* #include "strrchr.h" */
  970. /* #include "tctos.h" */
  971. /* #include "usage.h" */
  972. /* #include "warning.h" */
  973.